package cn.jbolt.core.service;

import cn.jbolt.core.base.JBoltMsg;
import cn.jbolt.core.common.enums.JBoltSystemLogTargetType;
import cn.jbolt.core.kit.JBoltUserKit;
import cn.jbolt.core.model.Role;
import cn.jbolt.core.model.User;
import cn.jbolt.core.service.base.JBoltBaseService;
import cn.jbolt.core.util.JBoltArrayUtil;
import com.jfinal.aop.Inject;
import com.jfinal.kit.Kv;
import com.jfinal.kit.Ret;

import java.util.ArrayList;
import java.util.List;

/**
 * 角色管理Service
 *
 * @ClassName: RoleService
 * @author: JFinal学院-小木 QQ：909854136
 * @date: 2019年3月27日 上午11:54:25
 */
public class JBoltRoleService extends JBoltBaseService<Role> {
	protected Role dao = new Role().dao();
	@Inject
	protected JBoltUserService jboltUserService;
	@Inject
	protected JBoltSystemLogService jboltSysteLogService;
	@Inject
	protected JBoltRolePermissionService jboltRolePermissionService;

	@Override
	protected Role dao() {
		return dao;
	}

	/**
	 * 保存role数据
	 *
	 * @param role
	 * @return
	 */
	public Ret save(Role role) {
		if (role == null || isOk(role.getId()) || notOk(role.getName())) {
			return fail(JBoltMsg.PARAM_ERROR);
		}
		String name = role.getName().trim();
		String sn = role.getSn();
		if (name.contains(" ")) {
			return saveAll(role.getPid(), JBoltArrayUtil.from3(name, " "), JBoltArrayUtil.from3(sn, " "));
		}
		if (existsName(name)) {
			return fail(JBoltMsg.DATA_SAME_NAME_EXIST + ":[" + name + "]");
		}
		if (isOk(sn)) {
			if (exists("sn", sn)) {
				return fail(JBoltMsg.DATA_SAME_SN_EXIST + ":[" + sn + "]");
			}
			role.setSn(sn);
		}
		role.setName(name);
		if (role.getPid() == null) {
			role.setPid(0L);
		}
		boolean success = role.save();
		if (success) {
			addSaveSystemLog(role.getId(), JBoltUserKit.getUserId(),
					role.getName() + "[" + role.getSn() + "]");
		}
		return success?successWithData(role):fail();
	}

	/**
	 * 添加多个
	 *
	 * @param pid
	 * @param names
	 * @param sns
	 * @return
	 */
	private Ret saveAll(Long pid, String[] names, String[] sns) {
		if (names == null) {
			return fail(JBoltMsg.PARAM_ERROR + "[名称]");
		}
		if (sns != null && names.length != sns.length) {
			return fail(JBoltMsg.DATA_NAME_SN_COUNT_NOT_EQUALS);
		}
		Ret ret = null;
		Role role;
		int index = 0;
		List<Role> roles = new ArrayList<>();
		for (String name : names) {
			role = new Role().setName(name).setPid(isOk(pid) ? pid : 0);
			if (sns != null) {
				role.setSn(sns[index].trim());
			}
			ret = save(role);
			if (ret.isFail()) {
				return ret;
			}
			roles.add(role);
			index++;
		}
		return successWithData(roles);
	}

	/**
	 * 修改role数据
	 *
	 * @param role
	 * @return
	 */
	public Ret update(Role role) {
		if (role == null || notOk(role.getId()) || notOk(role.getName())) {
			return fail(JBoltMsg.PARAM_ERROR);
		}
		String name = role.getName().trim();
		if (existsName(name, role.getId())) {
			return fail(JBoltMsg.DATA_SAME_NAME_EXIST + ":[" + name + "]");
		}
		String sn = role.getSn();
		if (isOk(sn)) {
			if (exists("sn", sn, role.getId())) {
				return fail(JBoltMsg.DATA_SAME_SN_EXIST + ":[" + sn + "]");
			}
			role.setSn(sn);
		}
		role.setName(name);
		boolean success = role.update();
		if (success) {
			addUpdateSystemLog(role.getId(), JBoltUserKit.getUserId(),
					role.getName());
		}
		return success?successWithData(findById(role.getId())):fail();
	}

	/**
	 * 删除
	 *
	 * @param id
	 * @return
	 */
	public Ret delete(Long id) {
		// 调用底层删除
		Ret ret = deleteById(id, true);
		if (ret.isOk()) {
			// 删除rolePermissions绑定
			Ret delRet = jboltRolePermissionService.deleteRolePermission(id);
			if (delRet.isFail()) {
				return delRet;
			}
			// 添加日志
			Role role = ret.getAs("data");
			addDeleteSystemLog(id, JBoltUserKit.getUserId(), role.getName());
		}
		return ret;
	}

	@Override
	public String checkCanDelete(Role role, Kv kv) {
		return checkInUse(role, kv);
	}

	@Override
	public String checkInUse(Role role, Kv kv) {
		boolean hasChild = checkHasChild(role.getId());
		if (hasChild) {
			return "此角色存在下级角色，不能直接删除";
		}
		boolean inUse = jboltUserService.checkRoleInUse(role.getId());
		return inUse ? "此角色已被用户分配使用，不能直接删除" : null;
	}

	/**
	 * 判断存在下级节点
	 *
	 * @param pid
	 * @return
	 */
	private boolean checkHasChild(Long pid) {
		return exists("pid", pid);
	}

	/**
	 * 得到所有角色是树形数据结构
	 *
	 * @return
	 */
	public List<Role> getAllRoleTreeDatas() {
		return convertToModelTree(findAll(), "id", "pid", (m) -> notOk(m.getPid()));
	}

	/**
	 * 得到用户可以管理访问的角色 树形数据结构
	 *
	 * @return
	 */
	public List<Role> getRoleTreeDatas(Long userId) {
		User user = jboltUserService.findById(userId);
		if (user == null || notOk(user.getRoles())) {
			return null;
		}
		if (user.getIsSystemAdmin()) {
			return getAllRoleTreeDatas();
		}

		List<Role> roles = find(selectSql().in("id", user.getRoles()));
		if (notOk(roles)) {
			return null;
		}
		roles.forEach(role -> {
			processSubRoles(role);
			role.put("isParent", true);
		});
		return convertToModelTree(roles, "id", "pid", (m) -> (notOk(m.getPid()) || m.getBoolean("isParent")));
	}

	private void processSubRoles(Role role) {
		List<Role> roles = getSons(role.getId());
		if (isOk(roles)) {
			roles.forEach(this::processSubRoles);
			role.putItems(roles);
			role.put("isParent", true);
		} else {
			role.put("isParent", false);
		}
	}

	@Override
	protected int systemLogTargetType() {
		return  JBoltSystemLogTargetType.ROLE.getValue();
	}
}
